#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <stddef.h>

// 字符函数
//  int main()
//  {
//      int ret = islower('X');
//      printf("%d\n", ret);
//      return 0;
//  }

// int main()
// {
//     int ret = isdigit('3');
//     printf("%d\n", ret);
//     return 0;
// }

// int main()
// {
//     int ret = toupper('a');
//     printf("%c\n", ret);
//     printf("%c\n", tolower(ret));
//     return 0;
// }

// int main()
// {
//     char arr[] = "Test String.\n";
//     char *p = arr;
//     while (*p)
//     {
//         if (isupper(*p))
//         {
//             *p = tolower(*p);
//         }
//         p++;
//     }
//     printf("%s\n", arr);

//     return 0;
// }

// 内存相关的函数
// memcpy的使用
// int main()
// {
//     int arr1[10] = {0};
//     int arr2[] = {1, 2, 3, 4, 5};
//     int sz = sizeof(arr2) / sizeof(arr2[0]);
//     // 把arr2中的数据拷贝到arr1中
//     memcpy(arr1, arr2, sz * sizeof(int));
//     for (int i = 0; i < sz; i++)
//     {
//         printf("%d ", arr2[i]);
//     }
//     printf("\n");
//     for (int i = 0; i < sz; i++)
//     {
//         printf("%d ", arr1[i]);
//     }
//     return 0;
// }

// memcpy的模拟实现

void *My_memcpy(void *dest, const void *src, size_t num)
{
    assert(dest && src);
    void *head = dest;
    for (size_t i = 0; i < num; i++)
    {
        *(char *)dest = *(char *)src;
        // ++的优先级比强转更高
        // (char *)dest++;
        // (char *)src++;

        // 这样可能会存在无法编译的问题
        // ++(char *)dest;
        // ++(char *)src;

        // 标准写法
        dest = (char *)dest + 1;
        src = (char *)src + 1;
    }
    return head;
}

// int main()
// {
//     char arr1[20] = {0};
//     char arr2[] = "abcdef";
//     int num = sizeof(arr2) / sizeof(arr2[0]) * sizeof(arr2[0]);
//     My_memcpy(arr1, arr2, num);
//     return 0;
// }

// 不重叠内存的拷贝，可以使用memcpy
// 重叠内存的拷贝，使用memmove函数

// memmove模拟实现

void *My_memmove(void *dest, const void *src, size_t sz)
{
    assert(dest && src);
    void *ret = dest;
    if (dest < src)
    {
        // 前->后
        for (size_t i = 0; i < sz; i++)
        {
            *(char *)dest = *(char *)src;
            dest = (char *)dest + 1;
            src = (char *)src + 1;
        }
    }
    else
    {
        // 后->前
        while (sz--)
        {
            *((char *)dest + sz) = *((char *)src + sz);
        }
    }
    return ret;
}

// int main()
// {
//     int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
//     My_memmove(arr, arr + 2, 20);
//     for (size_t i = 0; i < 10; i++)
//     {
//         printf("%d ", arr[i]);
//     }
//     printf("\n");
// }

// memcst是设置内存的，以字节为单位来设置内存
// int main()
// {
//     // char arr[] = "hello world";
//     // memset(arr + 6, 'x', 3);
//     // printf("%s\n", arr);

//     int arr[10] = {0};
//     memset(arr, 1, 40);
//     return 0;
// }

// memcmp是内存比较，以字节为单位来比较内存
// int main()
// {
//     int arr1[] = {1, 2, 3, 4, 5, 6, 7};
//     int arr2[] = {1, 2, 3, 7};
//     int ret = memcmp(arr1, arr2, 12);
//     printf("%d\n", ret);
//     return 0;
// }

struct Student
{
    char name[20];
    int age;
    char sex[5];
    float score;
} s1, s2, s3; // 是三个结构体变量  三个全局变量

struct Book
{
    char name[20];
    char author[12];
    float price;
};

// int main()
// {
//     struct Student s4, s5, s6; // 三个局部变量
//     return 0;
// }

// 特殊声明

// 匿名结构体,只能使用一次
// struct
// {
//     char name[20];
//     int age;
// } p1;

// 结构体的自引用

// error
//  struct Node
//  {
//      int data;
//      struct Node next;
//  }

// typedef struct Node
// {
//     int data;
//     struct Node *next;
//     // typedef给结构体取一个新名字Node，结构体可以简写
//     Node *nextnext;
// } Node;

// 多种多样的结构体初始化方式
// struct Point
// {
//     int x;
//     int y;
// } p1 = {1, 2};

// struct Point p3 = {4, 5};
// struct Stu
// {
//     char name[15];
//     int age;
// };
// int main()
// {
//     int a = 10;
//     int b = 20;
//     struct Point p2 = {a, b};
//     struct Stu s1 = {"zhangsan", 20};
//     // 如果不给定正确顺序，要使用.的方式初始化
//     struct Stu s2 = {.age = 18, .name = "lisi"};
//     return 0;
// }

// 结构体的嵌套
// struct Node2
// {
//     int data;
//     struct Point p;
//     struct Node *next;
// } n1 = {10, {4, 5}, NULL};            // 结构体嵌套初始化
// struct Node2 n2 = {20, {5, 6}, NULL}; // 结构体嵌套初始化

// 结构体内存对齐

// 计算结构体的大小
struct S1
{
    char c1;
    int i;
    char c2;
};
struct S2
{
    char c1;
    char c2;
    int i;
};

// offsetof 宏，可以直接使用
// 计算结构体成员相较于起始位置的偏移量
// #include <stddef.h>

int main()
{
    printf("%zu\n", sizeof(struct S1));
    printf("%zu\n", sizeof(struct S2));
    printf("%d\n", offsetof(struct S1, c1));
    printf("%d\n", offsetof(struct S1, i));
    printf("%d\n", offsetof(struct S1, c2));
    return 0;
}